package org.theqcp.wow.sim.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.LayoutStyle;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

/**
 * Non-modal alert for displaying exceptions.
 * 
 * This is not really the best way to handle these, but the log file is
 * sometimes difficult for a lineman to parse. This dialog attempts to bring the
 * exception right to the user for ease of debugging, and to make clear that
 * /something/ has gone terribly wrong.
 * 
 * @author bhamlin
 */
public class ScrollingExceptionDialog extends JFrame implements Runnable {

    private static final long serialVersionUID = -8203224957974871180L;

    public static void startNewInstance( Throwable e ) {
	SwingUtilities.invokeLater(new ScrollingExceptionDialog(e));
    }

    protected final Throwable exception;

    protected JScrollPane jScrollPane1;
    protected JTextPane txtException;
    protected JButton btnOK;

    /**
     * Creates new form ScrollingExceptionDialog
     */
    public ScrollingExceptionDialog(Throwable e) {
	exception = e;
	initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     */
    private void initComponents() {
	jScrollPane1 = new JScrollPane();
	txtException = new JTextPane();
	btnOK = new JButton();

	setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
	setTitle("Exception: " + exception.getClass().getName());
	setLocationByPlatform(true);
	setAlwaysOnTop(true);
	// setResizable(false);

	txtException.setBackground(UIManager.getDefaults().getColor("Button.background"));
	txtException.setEditable(false);
	txtException.setText(getTraceFromThrowable(exception));

	jScrollPane1.setBorder(BorderFactory.createEtchedBorder());
	jScrollPane1.setViewportView(txtException);

	btnOK.setText("OK");
	btnOK.setActionCommand("btnOK");
	btnOK.addActionListener(new ActionListener() {
	    public void actionPerformed( ActionEvent evt ) {
		btnOKActionPerformed(evt);
	    }
	});

	GroupLayout layout = new GroupLayout(getContentPane());
	getContentPane().setLayout(layout);
	layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
		layout.createSequentialGroup().addContainerGap().addGroup(
			layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(btnOK,
				GroupLayout.Alignment.TRAILING).addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE,
				589, Short.MAX_VALUE)).addContainerGap()));
	layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
		GroupLayout.Alignment.TRAILING,
		layout.createSequentialGroup().addContainerGap().addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE,
			446, Short.MAX_VALUE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(
			btnOK).addContainerGap()));

	pack();

	setSize(800, 600);
    }

    /**
     * Creates a presentable text form of an exception and accompanying stack
     * trace.
     * 
     * @param Exception e
     * @return String containing the exception message and stack trace.
     */
    protected String getTraceFromThrowable( Throwable e ) {
	StringBuffer b = new StringBuffer();

	b.append(e.getLocalizedMessage() + "\n");

	for( StackTraceElement traceStep: e.getStackTrace() ) {
	    b.append("\t" + traceStep.toString() + "\n");
	}

	return b.toString();
    }

    protected void btnOKActionPerformed( ActionEvent evt ) {
	this.dispose();
    }

    public void run() {
	this.setVisible(true);
    }

}
